package com.sunspring.zdcall.quartz.job;

import com.google.common.collect.Lists;
import com.sunspring.zdcall.datasource.DynamicDataSourceContextHolder;
import com.sunspring.zdcall.datasource.DynamicDataSourceRegister;
import com.sunspring.zdcall.dto.QueueDto;
import com.sunspring.zdcall.dto.SortQueue;
import com.sunspring.zdcall.entity.ZdBaseCheckroom;
import com.sunspring.zdcall.entity.ZdQueueInfo;
import com.sunspring.zdcall.service.CheckRoomService;
import com.sunspring.zdcall.service.DeptService;
import com.sunspring.zdcall.service.QueueService;
import com.sunspring.zdcall.support.cache.FlagTimeCache;
import com.sunspring.zdcall.support.cache.QueueCache;
import com.sunspring.zdcall.util.JsonUtil;
import com.sunspring.zdcall.util.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wulei
 * @date 2018-12-19
 **/
@Component
@Slf4j
public class RegisterJob implements Job {

    @Autowired
    private QueueService queueService;

    @Autowired
    private SimpMessagingTemplate smt;

    @Autowired
    private DeptService deptService;

    @Autowired
    private CheckRoomService crs;

    @Autowired
    private QueueCache queueCache;

    @Autowired
    private FlagTimeCache flagTimeCache;


    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        //获得数据源
        String source = Integer.toString(context.getJobDetail().getJobDataMap().getInt("source"));
        //设置数据源
        DynamicDataSourceContextHolder.setDataSourceType(source);
        Date flagTime = flagTimeCache.get(source);
        List<ZdQueueInfo> list = queueService.getQueueFromApi(flagTime);
        DynamicDataSourceContextHolder.clearDataSourceType();
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        generateQueue(list,source);
        long maxCheckInTime = list.stream().mapToLong(ZdQueueInfo::checkInTime).max().orElse(flagTime.getTime());
        flagTimeCache.set(source,new Date(maxCheckInTime));
        log.info("数据源:{}完成一次有效定时调度，flagTime更新为:{}",source,TimeUtil.format(new Date(maxCheckInTime)));
    }


    /**
     * 生成队列信息
     * @param queueInfoList 从登记系统查询的数据
     */
    private void generateQueue(List<ZdQueueInfo> queueInfoList,String source) {
        LinkedList<QueueDto> queueDtoList = Lists.newLinkedList();
        for(ZdQueueInfo qi : queueInfoList) {
            // 检查室信息检查
            ZdBaseCheckroom checkRoomInfo = queueService.deptCheck(qi);
            if (checkRoomInfo == null) {
                return;
            }
            String queuePrefix = checkRoomInfo.getQueuePrefix();
            String queueId = queueCache.getQueueId(qi.getCheckId(),checkRoomInfo.getQueueNumber());
            qi.setQueueId(queuePrefix + queueId);
            qi.setSource(source);
            qi.setCheckRoom(checkRoomInfo.getCheckRoomName());
            //添加队列信息到本地数据库
            int result = queueService.add(qi);
            if (result <= 0) {
                log.error("患者队列信息插入数据库失败，queueInfo={}",qi);
                continue;
            }
            //更新队列号缓存
            queueCache.setQueueId(qi.getCheckId(),queueId);

            //患者信息进缓存
            QueueDto queueDto = new QueueDto();
            BeanUtils.copyProperties(qi, queueDto);
            queueDto.setCheckRoomDisplayName(checkRoomInfo.getCheckRoomDisplayName());
            queueCache.add(queueDto);
            queueDtoList.addLast(queueDto);
        }

        //webSocket消息推送
        if (!queueDtoList.isEmpty()) {
            pushToClient(queueDtoList);
        }
    }



    /**
     * 消息推送
     *
     * @param queueDtoList 新增患者集合
     */
    private void pushToClient(LinkedList<QueueDto> queueDtoList) {
        Map<String, List<QueueDto>> checkRoomMap = queueDtoList.stream().collect(Collectors.groupingBy(QueueDto::getCheckId));
        Map<String, List<QueueDto>> deptMap = queueDtoList.stream().collect(Collectors.groupingBy(QueueDto::getDepartmentId));

        deptMap.forEach((s, list) -> {

            Map<String, List<QueueDto>> collect = list.stream().collect(Collectors.groupingBy(QueueDto::getCheckId));
            List<SortQueue> sortQueues = new LinkedList<>();
            collect.forEach((s1, list1) -> {
                SortQueue sortQueue = new SortQueue();
                sortQueue.setCheckId(s1);
                sortQueue.setCheckRoom(list1.get(0).getCheckRoom());
                sortQueue.setQueueDtoList(list1);
                sortQueues.add(sortQueue);
            });
            smt.convertAndSend("/newPatient/dept/" + s, JsonUtil.write(sortQueues));
        });
        //推送小屏
        checkRoomMap.forEach((s, list) -> {
            smt.convertAndSend("/newPatient/checkRoom/" + s, JsonUtil.write(list));
        });
    }
}
